"""
1. 什么是类型注解，有什么作用？
--------------------------------
在代码中涉及数据交互之时，对数据类型进行显式的说明，可以帮助：
- PyCharm等开发工具对代码做类型推断协助做代码提示
- 开发者自身做类型的备注

类型注解是一种在代码中指定变量、函数参数和返回值类型的语法，
它不强制执行类型检查，但可以为开发工具和开发者提供有用的信息。

2. 类型注解支持：
------------------
- 变量的类型注解
- 函数（方法）的形参和返回值的类型注解

3. 变量的类型注解语法
----------------------
语法1： 变量: 类型
语法2： 在注释中，# type: 类型

4. 函数（方法）可以为哪里添加注解？
------------------------------------
- 形参的类型注解
- 返回值的类型注解

5. 函数（方法）的类型注解语法？
---------------------------------
函数名(参数: 参数类型, ...) -> 返回值类型:

注意，返回值类型注解的符号使用： ->

6. 什么是Union类型？
---------------------
使用Union可以定义联合类型注解，表示一个变量可以是多种类型中的任意一种。

7. Union的使用方式
-------------------
导包：from typing import Union
使用：Union[类型, ......, 类型]

8. 注意事项
------------
类型注解只是提示性的，并非决定性的。数据类型和注解类型无法对应也不会导致错误
"""

# 导入typing模块，获取常用的类型注解
from typing import List, Dict, Tuple, Union, Optional

# 1. 变量的类型注解示例
# 语法1：变量: 类型
name: str = "张三"
age: int = 25
height: float = 1.75
is_student: bool = True

# 列表类型注解
scores: List[int] = [85, 92, 78, 96]
names: List[str] = ["张三", "李四", "王五"]

# 字典类型注解
student_info: Dict[str, Union[str, int]] = {
    "name": "张三",
    "age": 20,
    "grade": "大一"
}

# 元组类型注解
point: Tuple[int, int] = (10, 20)
person: Tuple[str, int, bool] = ("李四", 22, True)

# 可选类型注解(一个变量要么是指定的类型，要么是 None)
optional_name: Optional[str] = None
optional_name = "王五"  # 也可以赋值为字符串

# 联合类型注解（可以是多种类型中的一种）
id_number: Union[int, str] = 12345
id_number = "A12345"  # 也可以是字符串

# 更多Union类型示例
data: Union[int, float, str] = 10  # 可以是整数、浮点数或字符串
data = 3.14
data = "文本"

# 函数参数使用Union类型
def process_id(user_id: Union[int, str]) -> str:
    """
    处理用户ID，可以是整数或字符串
    
    Args:
        user_id (Union[int, str]): 用户ID
        
    Returns:
        str: 处理后的用户ID字符串
    """
    if isinstance(user_id, int):
        return f"ID_{user_id}"
    return user_id

# 函数返回值使用Union类型
def divide(a: float, b: float) -> Union[float, str]:
    """
    执行除法运算
    
    Args:
        a (float): 被除数
        b (float): 除数
        
    Returns:
        Union[float, str]: 计算结果或错误信息
    """
    if b == 0:
        return "错误：除数不能为零"
    return a / b

# 语法2：在注释中使用类型注解
address = "北京市"  # type: str
phone = 13800138000  # type: int
grades = [90, 85, 88]  # type: List[int]

# 2. 函数的类型注解示例
def greet(name: str) -> str:
    """
    打招呼函数
    
    Args:
        name (str): 姓名
        
    Returns:
        str: 打招呼的字符串
    """
    return f"你好，{name}！"

def calculate_area(length: float, width: float) -> float:
    """
    计算矩形面积
    
    Args:
        length (float): 长度
        width (float): 宽度
        
    Returns:
        float: 面积
    """
    return length * width

def get_student_info(name: str, age: int, scores: List[int]) -> Dict[str, Union[str, int, float]]:
    """
    获取学生信息
    
    Args:
        name (str): 姓名
        age (int): 年龄
        scores (List[int]): 分数列表
        
    Returns:
        Dict[str, Union[str, int, float]]: 学生信息字典
    """
    average = sum(scores) / len(scores)
    return {
        "name": name,
        "age": age,
        "average_score": average
    }

# 无返回值的函数使用None作为返回值类型
def print_message(message: str) -> None:
    """
    打印消息
    
    Args:
        message (str): 要打印的消息
    """
    print(message)

# 多个参数的函数示例
def create_user(name: str, age: int, email: str, active: bool = True) -> Dict[str, Union[str, int, bool]]:
    """
    创建用户信息
    
    Args:
        name (str): 用户姓名
        age (int): 用户年龄
        email (str): 用户邮箱
        active (bool, optional): 是否激活. Defaults to True.
        
    Returns:
        Dict[str, Union[str, int, bool]]: 用户信息字典
    """
    return {
        "name": name,
        "age": age,
        "email": email,
        "active": active
    }

# 3. 类方法的类型注解示例
class Student:
    """学生类"""
    
    def __init__(self, name: str, age: int) -> None:
        """
        初始化学生对象
        
        Args:
            name (str): 姓名
            age (int): 年龄
        """
        self.name = name
        self.age = age
        self.scores: List[int] = []
    
    def add_score(self, score: int) -> None:
        """
        添加分数
        
        Args:
            score (int): 分数
        """
        self.scores.append(score)
    
    def get_average(self) -> float:
        """
        计算平均分
        
        Returns:
            float: 平均分
        """
        if not self.scores:
            return 0.0
        return sum(self.scores) / len(self.scores)
    
    def get_info(self) -> Dict[str, Union[str, int, float]]:
        """
        获取学生信息
        
        Returns:
            Dict[str, Union[str, int, float]]: 学生信息
        """
        return {
            "name": self.name,
            "age": self.age,
            "average_score": self.get_average()
        }

# 4. 类型注解的实际使用示例
# 使用示例
# print(greet("张三"))
# area = calculate_area(5.0, 3.0)
# print(f"矩形面积: {area}")
# 
# student_data = get_student_info("李四", 20, [85, 92, 78])
# print(student_data)
# 
# student = Student("王五", 22)
# student.add_score(90)
# student.add_score(85)
# print(f"{student.name}的平均分: {student.get_average()}")

# 5. 类型注解的注意事项示例
# 类型注解只是提示性的，并不会强制类型检查
count: int = "这不是数字"  # 虽然注解为int，但实际可以赋值为字符串
# print(count)  # 这样不会报错

# 类型注解的真正价值在于：
# 1. 提高代码可读性
# 2. 支持IDE的智能提示
# 3. 支持静态类型检查工具（如mypy）
# 4. 便于团队协作和代码维护

# 常用的类型注解总结：
"""
基本类型：
- int: 整数
- float: 浮点数
- str: 字符串
- bool: 布尔值

容器类型：
- List[int]: 整数列表
- Dict[str, int]: 键为字符串、值为整数的字典
- Tuple[int, str]: 包含整数和字符串的元组

特殊类型：
- Optional[str]: 可选的字符串（等同于Union[str, None]）
- Union[int, str]: 整数或字符串
- Any: 任意类型
- None: 空值类型（用于无返回值的函数）

函数类型注解语法：
- 参数类型注解：参数名: 类型
- 返回值类型注解：-> 返回值类型

Union类型：
- 用于表示变量可以是多种类型中的任意一种
- 导入：from typing import Union
- 使用：Union[类型1, 类型2, ..., 类型n]
"""